﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SupportLibrary;

namespace DAL
{
    public static class DB
    {
        private static BlogModelContainer context = ModelDB.GetModelContainer();

        public static int CreateBlog(int userId, Blog newBlog)
        {
            if (context.Blog.Any(b => String.Equals(b.BlogName, newBlog.BlogName, StringComparison.CurrentCultureIgnoreCase)))
                throw new ArgumentException("Blog with same name already exists. BlogName: " + newBlog.BlogName);
            var user = GetUser(userId);
            if (user.Blog != null)
            {
                if (user.Blog.Deleted == false)
                    return 0;
                user.Deleted = false;
            }
            else
            {
                user.Blog = newBlog;
            }

            return context.SaveChanges();
        }

        public static Blog GetBlog(int blogId)
        {
            var specificBlog = context.Blog.FirstOrDefault(b => b.BlogId == blogId);
            if (specificBlog != null)
                return specificBlog;
            else
                throw new ArgumentException("Blog does not exist. ID: " + blogId);
        }

        public static Blog GetBlog(string blogName)
        {
            var specificBlog = context.Blog.FirstOrDefault(b => b.BlogName == blogName);
            if (specificBlog != null)
                return specificBlog;
            else
                throw new ArgumentException("Blog does not exist. Name: " + blogName);
        }


        public static int DeleteBlog(int id)
        {
            var blogToDelete = context.Blog.FirstOrDefault(b => b.BlogId == id);
            if (blogToDelete != null)
            {
                blogToDelete.Deleted = true;
                foreach (var blogPost in blogToDelete.BlogPost)
                {
                    blogPost.Deleted = true;
                    foreach (var comment in blogPost.BlogComments)
                        comment.Deleted = true;
                }
            }

            return context.SaveChanges();
        }

        public static int UpdateBlog(Blog updatedBlog)
        {
            var oldBlog = GetBlog(updatedBlog.BlogId);
            oldBlog.CopyProperties(updatedBlog);
            return context.SaveChanges();
        }

        public static int CreateBlogPost(int blogId, BlogPost post)
        {
            var blog = GetBlog(blogId);
            blog.BlogPost.Add(post);
            return context.SaveChanges();
        }

        public static BlogPost GetBlogPost(int blogPostId)
        {
            var blogPost = context.BlogPost.FirstOrDefault(b => b.BlogPostId == blogPostId);
            if (blogPost != null)
                return blogPost;
            else
                throw new ArgumentException("BlogPost does not exist. ID: " + blogPostId);
        }

        public static int DeleteBlogPost(int blogPostId)
        {
            var blogPost = GetBlogPost(blogPostId);
            blogPost.Deleted = true;
            foreach (var comment in blogPost.BlogComments)
                comment.Deleted = true;

            return context.SaveChanges();
        }

        public static int UpdateBlogPost(BlogPost updatedPost)
        {
            var oldBlog = GetBlogPost(updatedPost.BlogPostId);
            oldBlog.CopyProperties(updatedPost);
            return context.SaveChanges();
        }

        public static int CreateBlogRoll(int blogId, BlogRoll roll)
        {
            var blog = GetBlog(blogId);
            blog.BlogRollLink.Add(roll);
            return context.SaveChanges();
        }

        public static BlogRoll GetBlogRoll(int blogRollId)
        {
            var blogRoll = context.BlogRoll.FirstOrDefault(br => br.BlogRollId == blogRollId);
            if (blogRoll != null)
                return blogRoll;
            else
                throw new ArgumentException("BlogRoll does not exist. ID: " + blogRollId);
        }

        public static int DeleteBlogRoll(int blogRollId)
        {
            var blogRoll = GetBlogRoll(blogRollId);
            blogRoll.Deleted = true;
            return context.SaveChanges();
        }

        public static int UpdateBlogRoll(BlogRoll updatedRoll)
        {
            var blogRoll = GetBlogRoll(updatedRoll.BlogRollId);
            blogRoll.CopyProperties(updatedRoll);
            return context.SaveChanges();
        }

        public static int LogError(string errorMsg, DateTime time)
        {
            var errorObject = new ErrorCatching()
            {
                ErrorMessage = errorMsg,
                LoggedDate = time
            };
            context.ErrorCatching.Add(errorObject);
            return context.SaveChanges();
        }

        static public User GetUser(int id)
        {
            var specificUser = context.User.FirstOrDefault(u => u.UserId == id);
            if (specificUser != null)
                return specificUser;
            else
                throw new ArgumentException("User does not exist. ID: " + id);
        }

        static public User GetUser(string email)
        {
            var specificUser = context.User.FirstOrDefault(u => u.Email == email);
            if (specificUser != null)
                return specificUser;
            else
                throw new ArgumentException("Useremail does not exist. Email " + email);
        }

        static public int DeleteUser(int id)
        {
            var userToDelete = context.User.FirstOrDefault(u => u.UserId == id);
            if (userToDelete != null)
            {
                userToDelete.Deleted = true;
                userToDelete.Blog.Deleted = true; //redundant?
            }
            return context.SaveChanges();
        }

        static public int UpdateUser(User id)
        {
            var userToChange = context.User.FirstOrDefault(u => u.UserId == id.UserId);

            if (userToChange != null)
            {
                userToChange.CopyProperties(id);
            }
            return context.SaveChanges();

        }

        static public int CreateUser(User newUser)
        {
            if (!UserNameExists(newUser.Email))
                context.User.Add(newUser);
            return context.SaveChanges();
        }

        static public bool UserNameExists(string email)
        {
            var user = context.User
                .FirstOrDefault(u => u.Email == email);
            return (user != null);

        }

        public static int CreateBlogComment(int blogPostId, BlogComment comment)
        {
            var blogPost = GetBlogPost(blogPostId);
            blogPost.BlogComments.Add(comment);
            return context.SaveChanges();
        }

        public static BlogComment GetBlogComment(int blogCommentId)
        {
            var blogComment = context.BlogComment.FirstOrDefault(bc => bc.BlogCommentId == blogCommentId);
            if (blogComment != null)
                return blogComment;
            else
                throw new ArgumentException("BlogComment does not exist. ID: " + blogCommentId);
        }

        public static int DeleteBlogComment(int blogCommentId)
        {
            var comment = GetBlogComment(blogCommentId);
            comment.Deleted = true;
            return context.SaveChanges();
        }

        public static int UpdateBlogComment(BlogComment updateComment)
        {
            var comment = GetBlogComment(updateComment.BlogCommentId);
            comment.CopyProperties(updateComment);
            return context.SaveChanges();
        }




        public static bool AuthenticateLogin(string userName, string password, out Blog blog)
        {
            blog = null;
            var userExists = UserNameExists(userName);
            if (!userExists)
                return false;

            var query = context.User
                .FirstOrDefault(
                u => u.Email == userName && u.Password == password);

            if (query != null)
            {
                blog = query.Blog;
                return true;
            }
            throw new ArgumentException(string.Format("login error. wrong password. username: {0} password: {1}", userName, password));
        }
    }
}
